﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace ModbusTCPDLL
{
    public class ModTCP
    {
        Socket tcpclient;
        /// <summary>
        /// 建立Socket连接
        /// </summary>
        /// <param name="ip">IP地址</param>
        /// <param name="port">端口号</param>
        /// <returns></returns>
        public  bool Connect(string ip, string port)
        {
            IPEndPoint ie = new IPEndPoint(IPAddress.Parse(ip), Convert.ToInt32(port));
            tcpclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                tcpclient.Connect(ie);
            }
            catch (SocketException)
            {

                return false;
            }
            return true;
        }

        public void Disconnect()
        {
            if (tcpclient != null)
            {
                tcpclient.Disconnect(true);
            }
        
        }
        #region 读输出线圈  功能0x01
        /// <summary>
        /// 读输出线圈  功能0x01
        /// </summary>
        /// <param name="iAddress">从地址开始</param>
        /// <param name="iLength">读取多少长度</param>
        /// <param name="salveId">从站地址</param>
        /// <returns></returns>
        public byte[] ReadOutputStatus(int iAddress, int iLength,byte salveId = 3)
        {
            byte[] Result = null;
            //拼接发送报文
            ByteArray byteArray = new ByteArray(12);
            byteArray.Add(new byte[]
            {
            0,0,0,0,0,6,salveId,1          
            });
            byteArray.Add((byte)((iAddress - iAddress % 256) / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add((byte)((iLength - iLength % 256) / 256));
            byteArray.Add((byte)(iLength % 256));
            //发送报文
            tcpclient.Send(byteArray.array, byteArray.array.Length, SocketFlags.None);
            //接受报文
            byte[] data = new byte[512];
            tcpclient.Receive(data, 512, SocketFlags.None);

            //判断报文
            int length = 0;
            if (iLength % 8 == 0)
            {
                length = iLength / 8;
            }
            else
            {
                length = iLength / 8 + 1;
            }
            if (length == data[8])
            {
                //解析报文
                Result = ByteMsgToRes(data, 9, length);
            }
            return Result;
        }
        #endregion

        #region  强制输出线圈 功能码0x05
        /// <summary>
        /// 强制输出线圈 功能码0x05
        /// </summary>
        /// <param name="iAddress"></param>
        /// <param name="Value"></param>
        /// <returns></returns>
        public bool ForceOnOff(int iAddress, string Value, byte salveId = 3)
        {
            byte[] Result = null;
            //拼接发送报文
            ByteArray byteArray = new ByteArray(12);
            byteArray.Add(new byte[]
            {
            0,0,0,0,0,6,salveId,5          
            });
            byteArray.Add((byte)((iAddress - iAddress % 256) / 256));
            byteArray.Add((byte)(iAddress % 256));
            if (Value == "1" | Value.ToUpper() == "TRUE")
            {
                byteArray.Add(0xFF);
            }
            else
            {
                byteArray.Add(0);
            }
            byteArray.Add(0);
            //发送报文
            tcpclient.Send(byteArray.array, byteArray.array.Length, SocketFlags.None);
            //接受报文
            byte[] data = new byte[512];
            tcpclient.Receive(data, 512, SocketFlags.None);
            //解析报文
            Result = ByteMsgToRes(data, 0, 12);
            //判断报文
            if (Result.ToString() == byteArray.array.ToString())
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion

        #region 读保持型寄存器 功能码0x03
        /// <summary>
        /// 读保持型寄存器 功能码0x03
        /// </summary>
        /// <param name="iAddress"></param>
        /// <param name="iLength"></param>
        /// <returns></returns>
        public byte[] ReadKeepReg(int iAddress, int iLength, byte salveId = 3)
        {
            byte[] Result = null;
            //拼接发送报文
            ByteArray byteArray = new ByteArray(12);
            byteArray.Add(new byte[]
            {
            0,0,0,0,0,6,salveId,3          
            });
            byteArray.Add((byte)((iAddress - iAddress % 256) / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add((byte)((iLength - iLength % 256) / 256));
            byteArray.Add((byte)(iLength % 256));
            //发送报文
            tcpclient.Send(byteArray.array, byteArray.array.Length, SocketFlags.None);
            //接受报文
            byte[] data = new byte[512];
            tcpclient.Receive(data, 512, SocketFlags.None);

            //判断报文
            int length = iLength * 2;
            if (length == data[8])
            {
                //解析报文
                Result = ByteMsgToRes(data, 9, length);
            }
            return Result;

        }
        #endregion

        #region 预置单个寄存器 功能码0x06
        /// <summary>
        /// 预置单个寄存器 功能码0x06
        /// </summary>
        /// <param name="iAddress"></param>
        /// <param name="SetValue"></param>
        /// <returns></returns>
        public bool PreSetKeepReg(int iAddress, UInt16 SetValue, byte salveId = 3)
        {
            byte[] Result = null;
            //拼接发送报文
            ByteArray byteArray = new ByteArray(12);
            byteArray.Add(new byte[]
            {
            0,0,0,0,0,6,salveId,6         
            });
            byteArray.Add((byte)((iAddress - iAddress % 256) / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add((byte)((SetValue - SetValue % 256) / 256));
            byteArray.Add((byte)(SetValue % 256));

            //发送报文
            tcpclient.Send(byteArray.array, byteArray.array.Length, SocketFlags.None);
            //接受报文
            byte[] data = new byte[512];
            tcpclient.Receive(data, 512, SocketFlags.None);
            //解析报文
            Result = ByteMsgToRes(data, 0, 12);
            //判断报文
            if (Result.ToString() == byteArray.array.ToString())
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion

        #region  预置双字寄存器 功能码0x10
        /// <summary>
        /// 预置双字寄存器 功能码0x10
        /// </summary>
        /// <param name="iAddress"></param>
        /// <param name="SetValue"></param>
        /// <returns></returns>
        public bool PreSetFloatReg(int iAddress, float SetValue, byte salveId = 3)
        {
            byte[] Result = null;
            //拼接发送报文
            ByteArray byteArray = new ByteArray(12);
            byteArray.Add(new byte[]
            {
            0,0,0,0,0,11,salveId,16         
            });
            byteArray.Add((byte)((iAddress - iAddress % 256) / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add(new byte[]
            {
            0,2,4       
            });
            byte[] bSetValue = new byte[4];
            bSetValue = BitConverter.GetBytes(SetValue);
            byteArray.Add(bSetValue[1]);
            byteArray.Add(bSetValue[0]);
            byteArray.Add(bSetValue[3]);
            byteArray.Add(bSetValue[2]);
            //发送报文
            tcpclient.Send(byteArray.array, byteArray.array.Length, SocketFlags.None);
            //接受报文
            byte[] data = new byte[512];
            tcpclient.Receive(data, 512, SocketFlags.None);
            //解析报文
            Result = ByteMsgToRes(data, 0, 12);
            byte[] SendRes = ByteMsgToRes(byteArray.array, 0, 12);
            SendRes[6] = 6;
            //判断报文
            if (Result.ToString() == SendRes.ToString())
            {
                return true;
            }
            else
            {
                return false;
            }

        }
        #endregion

        #region 字节数组截取
        /// <summary>
        /// 字节数组截取
        /// </summary>
        /// <param name="MsgByte"></param>
        /// <param name="Start"></param>
        /// <param name="Length"></param>
        /// <returns></returns>
        public byte[] ByteMsgToRes(byte[] MsgByte, int Start, int Length)
        {
            byte[] Result = null;
            if (MsgByte != null && MsgByte.Length > 0)
            {
                Result = new byte[Length];
                for (int i = 0; i < Length; i++)
                {
                    Result[i] = MsgByte[i + Start];
                }
            }
            return Result;
        }
        #endregion
    }
}
